package cn.zhaoguang.usedcar.common.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.zhaoguang.usedcar.common.cache.CacheManage;
import cn.zhaoguang.usedcar.common.exception.AuthorizationException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description JwtToken工具
 * @Author zhaoguang
 * @Date 2021/3/12 0:51
 */
@Component
public class JwtTokenUtil implements Serializable {

    private static final long serialVersionUID = 1L;

    //手机号
    private static final String USERNAME = "username";
    //创建时间
    private static final String CREATED = "created";
    //密钥
    private static final String SECRET = "usedcar";


    @Autowired
    private CacheManage cacheManage;

    /**
     * @Description 生成Token
     * @Author zhaoguang
     */
    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(USERNAME, username);
        claims.put(CREATED, new Date());
        //生成Token
        String token = generateToken(claims);
        //保存手机号和Token到Redis中(单位：分钟)
        cacheManage.set(username, token, 5L);
        return token;
    }

    //从数据声明生成Token
    private String generateToken(Map<String, Object> claims) {
        String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, SECRET).compact();
        return token;
    }

    /**
     * @Description 验证Token
     * @Author zhaoguang
     */
    public boolean validateToken(String token) {
        if (StrUtil.isNotBlank(token)) {
            //从Token中获取数据声明
            Claims claims = getClaimsFromToken(token);
            if (ObjectUtil.isNotNull(claims)) {
                String username = (String) claims.get(USERNAME);
                //根据手机号从Redis中获取Token
                String redisToken = cacheManage.get(username);
                if (StrUtil.isNotBlank(redisToken)) {
                    if (redisToken.equals(token)) {
                        return true;
                    }
                    //缓存中token与传来的token不相同
                    throw new AuthorizationException("登录失败");
                }
                //缓存中无此token
                throw new AuthorizationException("登录已过期，请重新登录");
            }
            //解析签名出错
            throw new AuthorizationException("解析签名出错，请确认是否为正确Token");
        }
        //token为空
        throw new AuthorizationException("Token为空");
    }

    //从Token中获取数据声明
    private Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    /**
     * @Description 移除Token
     * @Author zhaoguang
     */
    public boolean removeToken(String username) {
        boolean res = cacheManage.remove(username);
        return res;
    }

}